<template>
  <div style="width: 100%; height: 100%; display: flex; align-items: center">
    <div
      style="
        display: grid;
        grid-template-columns: 3fr 5fr;
        grid-gap: 10px;
        width: 100%;
      "
    >
      <div
        class="chartDom"
        :class="props.className"
        ref="chartRef"
        :style="{
          height: props.height,
          width: '100%',
          border: props.border,
          //   backgroundImage: `url(${require('@/assets/images/chart_opacity_bg.png')})`,
          backgroundRepeat: 'no-repeat',
          backgroundPosition: 'center center',
        }"
      ></div>
      <div style="display: grid; grid-template-columns: 1fr 1fr">
        <div v-for="item in dataFormPie">
          {{ item.name
          }}<span style="font-size: 16px; font-weight: 900; margin: 0px 2px">{{
            item.bfb
          }}</span>
          <span
            :style="{ color: getColor(item.value) }"
            style="font-size: 16px"
          >
            {{ item.value }}</span
          >
        </div>
      </div>
    </div>
  </div>
</template>
<!-- 饼图 -->
<!-- <div class="container">
    <div class="chartsGl" id="charts"></div>
     <div class="buttomCharts"></div>
</div> -->

<script setup lang="ts">
import { ref, reactive, onMounted, defineProps, nextTick } from "vue";
import * as echarts from "echarts";
import "echarts-gl";
const imgDom = ref(null);
// require()
import "echarts/theme/macarons";
// 定义组件的 props
const props = defineProps({
  className: { type: String, default: "chart" },
  width: { type: String, default: "40%" },
  height: { type: String, default: "150px" },
  border: { type: String, default: "" },
  optionTest: { type: Object, default: () => ({}) },
});
const dataFormPie = ref([
  { id: 1, name: "中国银行", bfb: "80%", value: 1665 },
  { id: 2, name: "建设银行", bfb: "80%", value: 50 },
  { id: 3, name: "工商银行", bfb: "80%", value: 150 },
  { id: 4, name: "农业银行", bfb: "80%", value: 300 },
  { id: 5, name: "招商银行", bfb: "80%", value: 199 },
]);
function getColor(value: number) {
  if (value < 50) return "#ff4d4f";
  if (value < 100) return "#fa8c16";
  if (value < 150) return "#a0d911";
  if (value < 200) return "#13c2c2";
  if (value < 250) return "#1890ff";
  if (value < 300) return "#722ed1";
  if (value < 350) return "#eb2f96";
  if (value < 400) return "#9012fe";
  return "#fa541c";
}
// 定义图表的引用
const chartRef = ref<HTMLDivElement | null>(null);
// 定义 echarts 实例
let myChart: echarts.ECharts | null = null;

// 定义饼图的数据
const optionData = reactive([
  { id: 1, name: "中国银行", bfb: "80%", value: 1665 },
  { id: 2, name: "建设银行", bfb: "80%", value: 50 },
  { id: 3, name: "工商银行", bfb: "80%", value: 150 },
  { id: 4, name: "农业银行", bfb: "80%", value: 300 },
  { id: 5, name: "招商银行", bfb: "80%", value: 199 },
]);

// 定义 echarts 的配置项
let option: any = null;

// 格式化浮点数
function fomatFloat(num: number, n: number) {
  let f = parseFloat(num as any);
  if (isNaN(f)) return false;
  f = Math.round(num * Math.pow(10, n)) / Math.pow(10, n);
  let s = f.toString();
  let rs = s.indexOf(".");
  if (rs < 0) {
    rs = s.length;
    s += ".";
  }
  while (s.length <= rs + n) {
    s += "0";
  }
  return s;
}

// 计算3D饼图的高度
function getHeight3D(series: any[], height: number) {
  series.sort((a, b) => b.pieData.value - a.pieData.value);
  return (height * 25) / series[0].pieData.value;
}

// 获取参数方程
function getParametricEquation(
  startRatio: number,
  endRatio: number,
  isSelected: boolean,
  isHovered: boolean,
  k: number,
  h: number
) {
  let midRatio = (startRatio + endRatio) / 2;
  let startRadian = startRatio * Math.PI * 2;
  let endRadian = endRatio * Math.PI * 2;
  let midRadian = midRatio * Math.PI * 2;
  if (startRatio === 0 && endRatio === 1) isSelected = false;
  k = typeof k !== "undefined" ? k : 1 / 3;
  let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
  let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
  let hoverRate = isHovered ? 1.05 : 1;
  return {
    u: { min: -Math.PI, max: Math.PI * 3, step: Math.PI / 32 },
    v: { min: 0, max: Math.PI * 2, step: Math.PI / 20 },
    x: function (u: number, v: number) {
      if (u < startRadian)
        return (
          offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate
        );
      if (u > endRadian)
        return (
          offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate
        );
      return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
    },
    y: function (u: number, v: number) {
      if (u < startRadian)
        return (
          offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate
        );
      if (u > endRadian)
        return (
          offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate
        );
      return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
    },
    z: function (u: number, v: number) {
      if (u < -Math.PI * 0.5) return Math.sin(u);
      if (u > Math.PI * 2.5) return Math.sin(u) * h * 0.1;
      return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
    },
  };
}

// 获取3D饼图的配置项
function getPie3D(pieData: any[], internalDiameterRatio: number) {
  let series: any[] = [];
  let sumValue = 0;
  let startValue = 0;
  let endValue = 0;
  let legendData: any[] = [];
  let legendBfb: any[] = [];
  let k = 1 - internalDiameterRatio;
  pieData.sort((a, b) => b.value - a.value);
  for (let i = 0; i < pieData.length; i++) {
    sumValue += pieData[i].value;
    let seriesItem: any = {
      name:
        typeof pieData[i].name === "undefined" ? `series${i}` : pieData[i].name,
      type: "surface",
      parametric: true,
      wireframe: { show: false },
      pieData: pieData[i],
      pieStatus: { selected: false, hovered: false, k: k },
    };
    if (typeof pieData[i].itemStyle != "undefined") {
      let itemStyle: any = {};
      if (pieData[i].itemStyle.color) itemStyle.color = "#ffe152"; // pieData[i].itemStyle.color
      if (pieData[i].itemStyle.opacity)
        itemStyle.opacity = pieData[i].itemStyle.opacity;
      seriesItem.itemStyle = itemStyle;
    }
    series.push(seriesItem);
  }
  legendData = [];
  legendBfb = [];
  for (let i = 0; i < series.length; i++) {
    endValue = startValue + series[i].pieData.value;
    series[i].pieData.startRatio = startValue / sumValue;
    series[i].pieData.endRatio = endValue / sumValue;
    series[i].parametricEquation = getParametricEquation(
      series[i].pieData.startRatio,
      series[i].pieData.endRatio,
      false,
      false,
      k,
      series[i].pieData.value
    );
    startValue = endValue;
    let bfb = fomatFloat(series[i].pieData.value / sumValue, 4);
    legendData.push({ name: series[i].name, value: bfb });
    legendBfb.push({ name: series[i].name, value: bfb });
  }
  let boxHeight = getHeight3D(series, 15);
  let option = {
    grid: {
      left: "0%",
      right: "0%",
      bottom: "0%",
      top: "10%",
      containLabel: true,
    },
    legend: {
      data: legendData,
      orient: "horizontal",
      type: "scroll",
      show: false,
      left: "0%",
      bottom: "5%",
      itemGap: 0,
      textStyle: { color: "black", fontSize: "0.5rem" },
      //   show: true,
      icon: "circle",
      formatter: function (param: any) {
        let item = legendBfb.filter((item) => item.name == param)[0];
        let bfs = fomatFloat(item.value * 100, 2) + "%";
        console.log(bfs, 195);
        return `${item.name} :${bfs}`;
      },
    },
    tooltip: {
      show: true,
      formatter: (params: any) => {
        if (
          params.seriesName !== "mouseoutSeries" &&
          params.seriesName !== "pie2d"
        ) {
          let bfb = (
            (option.series[params.seriesIndex].pieData.endRatio -
              option.series[params.seriesIndex].pieData.startRatio) *
            100
          ).toFixed(2);
          return (
            `${params.seriesName}<br/>` +
            `<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${params.color};"></span>` +
            `${bfb}%`
          );
        }
      },
    },
    xAxis3D: { min: -0.8, max: 1 },
    yAxis3D: { min: -1, max: 1 },
    zAxis3D: { min: -1, max: 1 },
    grid3D: {
      show: false,
      boxHeight: boxHeight,
      top: "-10%",
      viewControl: {
        alpha: 35,
        distance: 165,
        rotateSensitivity: 1,
        zoomSensitivity: 0,
        panSensitivity: 0,
        autoRotate: false,
      },
    },
    series: series,
  };
  return option;
}

// 绑定图表的事件监听器
function bindListen(myChart: echarts.ECharts) {
  let selectedIndex: any = "";
  let hoveredIndex: any = "";
  myChart.on("click", function (params: any) {
    let isSelected = !option.series[params.seriesIndex].pieStatus.selected;
    let isHovered = option.series[params.seriesIndex].pieStatus.hovered;
    let k = option.series[params.seriesIndex].pieStatus.k;
    let startRatio = option.series[params.seriesIndex].pieData.startRatio;
    let endRatio = option.series[params.seriesIndex].pieData.endRatio;
    if (selectedIndex !== "" && selectedIndex !== params.seriesIndex) {
      option.series[selectedIndex].parametricEquation = getParametricEquation(
        option.series[selectedIndex].pieData.startRatio,
        option.series[selectedIndex].pieData.endRatio,
        false,
        false,
        k,
        option.series[selectedIndex].pieData.value
      );
      option.series[selectedIndex].pieStatus.selected = false;
    }
    option.series[params.seriesIndex].parametricEquation =
      getParametricEquation(
        startRatio,
        endRatio,
        isSelected,
        isHovered,
        k,
        option.series[params.seriesIndex].pieData.value
      );
    option.series[params.seriesIndex].pieStatus.selected = isSelected;
    if (isSelected) selectedIndex = params.seriesIndex;
    myChart.setOption(option);
  });
  myChart.on("mouseover", function (params: any) {
    let isSelected, isHovered, startRatio, endRatio, k;
    if (hoveredIndex === params.seriesIndex) return;
    else {
      if (hoveredIndex !== "") {
        isSelected = option.series[hoveredIndex].pieStatus.selected;
        isHovered = false;
        startRatio = option.series[hoveredIndex].pieData.startRatio;
        endRatio = option.series[hoveredIndex].pieData.endRatio;
        k = option.series[hoveredIndex].pieStatus.k;
        option.series[hoveredIndex].parametricEquation = getParametricEquation(
          startRatio,
          endRatio,
          isSelected,
          isHovered,
          k,
          option.series[hoveredIndex].pieData.value
        );
        option.series[hoveredIndex].pieStatus.hovered = isHovered;
        hoveredIndex = "";
      }
      if (
        params.seriesName !== "mouseoutSeries" &&
        params.seriesName !== "pie2d"
      ) {
        isSelected = option.series[params.seriesIndex].pieStatus.selected;
        isHovered = true;
        startRatio = option.series[params.seriesIndex].pieData.startRatio;
        endRatio = option.series[params.seriesIndex].pieData.endRatio;
        k = option.series[params.seriesIndex].pieStatus.k;
        option.series[params.seriesIndex].parametricEquation =
          getParametricEquation(
            startRatio,
            endRatio,
            isSelected,
            isHovered,
            k,
            option.series[params.seriesIndex].pieData.value + 5
          );
        option.series[params.seriesIndex].pieStatus.hovered = isHovered;
        hoveredIndex = params.seriesIndex;
      }
      myChart.setOption(option);
    }
  });
  myChart.on("globalout", function () {
    let isSelected, isHovered, startRatio, endRatio, k;
    if (hoveredIndex !== "") {
      isSelected = option.series[hoveredIndex].pieStatus.selected;
      isHovered = false;
      k = option.series[hoveredIndex].pieStatus.k;
      startRatio = option.series[hoveredIndex].pieData.startRatio;
      endRatio = option.series[hoveredIndex].pieData.endRatio;
      option.series[hoveredIndex].parametricEquation = getParametricEquation(
        startRatio,
        endRatio,
        isSelected,
        isHovered,
        k,
        option.series[hoveredIndex].pieData.value
      );
      option.series[hoveredIndex].pieStatus.hovered = isHovered;
      hoveredIndex = "";
    }
    myChart.setOption(option);
  });
}

// 在组件挂载后初始化图表
onMounted(() => {
  nextTick(() => {
    if (chartRef.value) {
      myChart = echarts.init(chartRef.value, "macarons");
      option = getPie3D(optionData, 0.85);
      myChart.setOption(option);
      bindListen(myChart);
    }
  });
});
</script>

<style>
.chart {
  background-size: 60% 60%;
  /* background:rgba(34,34,34,0.5); */
}
.chartDom {
  background-image: url("/pieBak.png");
  background-size: 100% 100%;
}
</style>
